package cn.ilikes.tools.untils;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import cn.ilikes.tools.hbase.jpa.JPAHbasePersistenUnitEnv;
import cn.ilikes.tools.hbase.jpa.JPAHbasePersistenceProvider;
import cn.ilikes.tools.hbase.jpa.clients.nodes.Node;
import cn.ilikes.tools.hbase.jpa.metadatas.IEntityMetaData;
import cn.ilikes.tools.hbase.jpa.metadatas.IEntityMetaDataFactory;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.EntityFields;
import cn.ilikes.tools.untils.propertys.PropertiesUtils;
import cn.ilikes.tools.untils.propertys.PropertyAccessException;

public class PropertyAccessorHelper {

	public static byte[] getObjectToByte(Object from, Field field) {
		Object oj = getObject(from, field);
		return HBaseUtils.getBytes(oj);

	}

	public static Object getObject(Object from, Field field) {

		if (!field.isAccessible()) {
			field.setAccessible(true);
		}

		try {
			if (from == null || field == null) {
				throw new PropertyAccessException(" form  is " + from + " or  field : " + field + " not get field value from from Object");
			}
			return field.get(from);
		} catch (IllegalArgumentException iarg) {
			throw new PropertyAccessException(iarg);
		} catch (IllegalAccessException iacc) {
			throw new PropertyAccessException(iacc);
		}
	}

	public static Object getId(Object entity, IEntityMetaData metadata) {

		EntityFields entityFields = metadata.getEntityId();
		Field field = entityFields.getField();
		Object id = getObject(entity, field);
		return id;
	}

	public static Object getId(Node node) {

		EntityFields entityFields = node.getEntityMetaData().getEntityId();
		Field field = entityFields.getField();
		Object id = getObject(node.getEntity(), field);
		return id;
	}

	public static Object fieldValue(Object entity, Field field) {

		return getObject(entity, field);
	}

	public static Object getJPAEntityId(String puName, Object fieldValue) {
		JPAHbasePersistenUnitEnv hbasePersistenUnitEnv = JPAHbasePersistenceProvider.findJPAHbasePersistenUnitEnv(puName);
		IEntityMetaDataFactory entityMetaDataFactory = hbasePersistenUnitEnv.getEntityMetaDataFactory();
		IEntityMetaData entityMetaData = entityMetaDataFactory.selectIEntityMetaData(fieldValue.getClass());
		return PropertyAccessorHelper.getId(fieldValue, entityMetaData);
	}

	public static Class<?> getGenericClass(Field collectionField) {
		Class<?> genericClass = null;
		if (collectionField == null) {
			return genericClass;
		}
		if (isCollection(collectionField.getType())) {

			Type[] parameters = PropertiesUtils.getTypeArguments(collectionField);
			if (parameters != null) {
				if (parameters.length == 1) {
					genericClass = (Class<?>) parameters[0];
				} else {
					throw new PropertyAccessException("Can't determine generic class from a field that has two parameters.");
				}
			}
		}
		return genericClass != null ? genericClass : collectionField.getType();
	}

	public static final boolean isCollection(Class<?> clazz) {
		return Collection.class.isAssignableFrom(clazz);

	}

	public static final boolean isSet(Class<?> clazz) {
		return Set.class.isAssignableFrom(clazz);

	}

	public static final boolean isList(Class<?> clazz) {
		return List.class.isAssignableFrom(clazz);

	}

	public static final Field findField(Class<?> clazz, String fieldName) {
		try {
			return clazz.getDeclaredField(fieldName);
		} catch (SecurityException e) {
			e.printStackTrace();
			return null;
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
			return null;
		}

	}

}
